/*********************************
*-- 33 KDH Knieja ---------------*
*-- im. Harcerzy Września 1939 --*
*-- autor: Marcin Rzepisko ------*
*-- data: 2013-11-16 ------------*
**********************************/

package net.kdh.knieja.dao.klasy;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import net.kdh.knieja.dao.klasy.filtry.FiltrDAO;
import net.kdh.knieja.dao.klasy.sqlgenerator.SqlGenerator;
import net.kdh.knieja.dao.polaczenie.ParametryPolaczenia;
import net.kdh.knieja.dao.polaczenie.PolaczenieBazy;
import net.kdh.knieja.model.wspolne.LMD;
import net.kdh.knieja.model.wspolne.wyjatki.BladWarstwyDaoWyjatek;

/**
 *
 * @author rz.marcin@gmail.com
 */
public abstract class KlasaDAO<K extends LMD>{
    private PolaczenieBazy polaczenie;
    private SqlGenerator sqlGenerator;
    
    
    protected KlasaDAO(SqlGenerator sqlGenerator) {
        setSqlGenerator(sqlGenerator);
    }
    
    public final void initConnection(ParametryPolaczenia parametry) {
        setPolaczenie(new PolaczenieBazy(parametry));
    }
    public final void closeConnection() throws BladWarstwyDaoWyjatek {
        try {
        polaczenie.disconnect();
        }
        catch (SQLException ex) {
            throw new BladWarstwyDaoWyjatek("KlasaDAO.closeConnection()", ex);
        }
    }
    protected abstract List<K> parseResultSet(ResultSet rs) throws BladWarstwyDaoWyjatek;
    
    public final String zapisz(K klasa) throws BladWarstwyDaoWyjatek {
        Statement st = polaczenie.getStatement();
        String id = "";
        
        polaczenie.startTransaction();
        String query = sqlGenerator.generujInsert(klasa);
        ResultSet rs;
        try {
        st.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
        rs = st.getGeneratedKeys();
        
        if(rs.next()) {
            id = rs.getString(1);
        } else {
            rs.close();
            return null;
        }
        rs.close();
        polaczenie.commit();
        } catch (SQLException ex) {
            System.out.println("Błąd SQL" + "\n" + ex.getLocalizedMessage());
            polaczenie.rollback();
            throw new BladWarstwyDaoWyjatek("KlasaDAO.zapisz()", ex);
        }
        
        return id;
    }
    
    public final List<K> pobierzListeElementow(FiltrDAO filtr) throws BladWarstwyDaoWyjatek {
        List<K> wynik = new ArrayList<>(0);
        Statement st = polaczenie.getStatement();
        String query = sqlGenerator.generujSelect(filtr);
        
        try {
        wynik = parseResultSet(st.executeQuery(query));
        }
        catch (SQLException ex) {
            System.out.println("Błąd SQL" + "\n" + ex.getLocalizedMessage());
            throw new BladWarstwyDaoWyjatek("KlasaDAO.pobierzListeElementow()", ex);
        }
        return wynik;
    }
    
    public final void aktualizuj(K klasa) throws BladWarstwyDaoWyjatek {
        Statement st = polaczenie.getStatement();
        
        polaczenie.startTransaction();
        String query = sqlGenerator.generujUpdate(klasa);
        try {
        st.executeUpdate(query);
        polaczenie.commit();
        } catch (SQLException ex) {
            System.out.println("Błąd SQL" + "\n" + ex.getLocalizedMessage());
            polaczenie.rollback();
            throw new BladWarstwyDaoWyjatek("KlasaDAO.aktualizuj()", ex);
        }
    }

    public final void usun(String id) throws BladWarstwyDaoWyjatek {
        Statement st = polaczenie.getStatement();
        
        polaczenie.startTransaction();
        String query = sqlGenerator.generujDelete(id);
        try {
        st.executeUpdate(query);
        polaczenie.commit();
        } catch (SQLException ex) {
            System.out.println("Błąd SQL" + "\n" + ex.getLocalizedMessage());
            polaczenie.rollback();
            throw new BladWarstwyDaoWyjatek("KlasaDAO.usun()", ex);
        }
    }
    @Override
    protected void finalize() throws Throwable {
        polaczenie.disconnect();
        super.finalize(); 
    }

    protected final void setPolaczenie(PolaczenieBazy polaczenie) {
        this.polaczenie = polaczenie;
    }

    protected final void setSqlGenerator(SqlGenerator sqlGenerator) {
        this.sqlGenerator = sqlGenerator;
    }
}
